using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace HWEngine
{
	[Serializable]
	public class Line
	{
		[XmlArrayItem(ElementName = "Point")]
		public List<PointF> Points { get; set; }

		[XmlIgnore]
		public Color Color { get; set; }

		[XmlAttribute("Color")]
		public string HexColor
		{
			get
			{
				return Color.ToArgb().ToString("X");
			}

			set
			{
				Color = Color.FromArgb(Convert.ToInt32(value, 16));
			}
		}

		[XmlIgnore]
		public string HtmlColor
		{
			get
			{
				return "#" + HexColor.Substring(2);
			}
		}

		[XmlAttribute("Width")]
		public double Width { get; set; }

		[XmlAttribute("Tension")]
		public float Tension { get; set; }

		[XmlAttribute("StartIndex")]
		public int StartIndex { get; set; }

		[XmlAttribute("FinishIndex")]
		public int FinishIndex { get; set; }

		[XmlAttribute("StartConcatMode")]
		public ConcatMode StartConcatMode { get; set; }

		[XmlAttribute("FinishConcatMode")]
		public ConcatMode FinishConcatMode { get; set; }

		public Line()
		{
			Points = new List<PointF>();

			Tension = 0.5f;
			Width = 1f;
			Color = Color.Black;
		}

		public Line Clone()
		{
			return Clone(true);
		}

		public Line Clone(bool withPoints)
		{
			return new Line
			{
				Color = Color,
				Width = Width,
				Tension = Tension,
				StartIndex = StartIndex,
				FinishIndex = FinishIndex,
				StartConcatMode = StartConcatMode,
				FinishConcatMode = FinishConcatMode,
				Points = withPoints ? new List<PointF>(Points) : new List<PointF>()
			};
		}

		public void SetPointConcatMode(int pointIndex, ConcatMode mode)
		{
			if (pointIndex < Points.Count / 2)
			{
				StartConcatMode = mode;
				StartIndex = pointIndex;
			}
			else
			{
				FinishIndex = pointIndex;
				FinishConcatMode = mode;
			}
		}

		public unsafe void Shift(double xoffset, double yoffset)
		{
			for (int i = 0; i < Points.Count; i++)
			{
				PointF p = Points[i];
				p.X += (float) xoffset;
				p.Y += (float) yoffset;
				Points[i] = p;
			}
		}

		public unsafe void Scale(double xoffset, double yoffset)
		{
			for (int i = 0; i < Points.Count; i++)
			{
				PointF p = Points[i];
				p.X *= (float) xoffset;
				p.Y *= (float) yoffset;
				Points[i] = p;
			}
		}

		public void InsertPoint(PointF point, int index)
		{
			if (index < 0)
			{
				Points.Add(point);
			}
			else
			{
				if (index <= StartIndex)
				{
					++StartIndex;
				}
				if (index <= FinishIndex)
				{
					++FinishIndex;
				}

				Points.Insert(index, point);
			}
		}

		public void RemovePoint(int index)
		{
			if (index <= StartIndex)
			{
				--StartIndex;
			}
			if (index <= FinishIndex)
			{
				--FinishIndex;
			}

			Points.RemoveAt(index);
		}

		public PointF StartPoint
		{
			get
			{
				if (StartIndex >= 0)
				{
					return Points[StartIndex];
				}
				else
				{
					return Points[0];
				}
			}
		}

		public PointF FinishPoint
		{
			get
			{
				if (FinishIndex >= 0)
				{
					return Points[FinishIndex];
				}
				else
				{
					return Points[Points.Count - 1];
				}
			}
		}

		public int LastPointIndex
		{
			get
			{
				return Points.Count - 1;
			}
		}
	}
}